'''
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http:#www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
'''
from base.graph.impl.FrontsNode import FrontsNode

#import org.apache.jena.graph.*;
#import org.apache.jena.rdf.model.*;

'''
 * <p>
 * A specialisation of Polymorphic that models an extended node in a an extended graph. An extended node
 * wraps a normal node, and adds additional convenience access or user affordances, though the state
 * remains in the graph itself.
 * </p>
'''
from abc import ABC, abstractmethod

class EnhNode(FrontsNode):

    '''
     * The graph node that this enhanced node is wrapping
    '''
    #final protected Node
    node = None

    '''
     * The enhanced graph containing this node
    '''
    #final protected EnhGraph
    enhGraph = None

    # param Node n, EnhGraph g:
    def __init__(self, n, g):
        super().__init__()
        self.node = n
        self.enhGraph = g
    

    # External interface

    '''
     * Answer the graph node that this enhanced node wraps
     *
     * @return A plain node
    '''
    #@Override
    # param 
    # result Node
    def asNode(self):
        return self.node
    

    '''
     * Answer the graph containing this node
     *
     * @return An enhanced graph
    '''
    # param 
    # result EnhGraph
    def getGraph(self):
        return self.enhGraph
    

    '''
     * An enhanced node is Anon[ymous] iff its underlying node is Blank.
    '''
    # param 
    # result final boolean
    def isAnon(self):
        return self.node.isBlank()
    

    '''
     * An enhanced node is Literal iff its underlying node is too.
    '''
    # param 
    # result final boolean
    def isLiteral(self):
        return self.node.isLiteral()
    

    '''
     * An enhanced node is a URI resource iff its underlying node is too.
    '''
    # param 
    # result final boolean
    def isURIResource(self):
        return self.node.isURI()
    

    '''
     * An enhanced node is a statement resource iff its underlying node is a triple term (RDF-star).
    '''
    # param 
    # result final boolean
    def isStmtResource(self):
        return self.node.isNodeTriple()
    

    '''
     * An enhanced node is a resource if it's node is a URI node, a blank node or a triple term.
    '''
    # param 
    # result final boolean
    def isResource(self):
        return self.node.isURI() or self.node.isBlank() or self.node.isNodeTriple()
    

    '''
     * Answer a facet of this node, where that facet is denoted by the
     * given type.
     *
     * @param t A type denoting the desired facet of the underlying node
     * @return An enhanced nodet that corresponds to t this may be <i>this</i>
     * Java object, or a different object.
    '''
    # param Class<X> t
    # result <X extends RDFNode> X
    def viewAs(self, t):
        return self.asInternal(t)
    

    '''
     * allow subclasses to implement RDFNode &amp its subinterface
    '''
    # param Class<T> t
    # result <T extends RDFNode> T
    def asInner(self, t):
        return self.asInternal(t)
    

    '''
     * API-level method for polymorphic testing
    '''
    # param Class<X> t
    # result <X extends RDFNode> boolean
    def canAs(self, t):
        return self.canSupport(t)
    

    '''
     * The hash code of an enhanced node is defined to be the same as the underlying node.
     *
     * @return The hashcode as an int
    '''
    #@Override
    # param 
    # result int
    def hashCode(self):
        return self.node.hashCode()
    

    '''
     * An enhanced node is equal to another enhanced node n iff the underlying
     * nodes are equal. We generalise to allow the other object to be any class
     * implementing asNode, because we allow other implemementations of
     * Resource than EnhNodes, at least in principle.
     * This is deemed to be a complete and correct interpretation of enhanced node
     * equality, which is why this method has been marked final.
     *
     * @param o An object to test for equality with this node
     * @return True if o is equal to this node.
    '''
    #@Override
    # param Object o
    # result boolean
    def equals(self, o):
        return isinstance(o, FrontsNode) and self.node.equals(o)
        #return o instanceof FrontsNode && node.equals(((FrontsNode) o).asNode())
    

    #@Override
    # param 
    # result boolean
    def isValid(self):
        return True
    

    '''
     * Answer an new enhanced node object that presents <i>this</i> in a way
     * which satisfies type <code>t</code>. The new object is linked into this
     * object's sibling ring. If the node cannot be converted, throw an
     * UnsupportedPolymorphismException.
    '''
    #@Override
    # param Class<X> t
    # result <X extends RDFNode> X
    def convertTo(self, t):
        #EnhGraph
        eg = self.getGraph()
        # if eg is None:
        #     raise UnsupportedPolymorphismException(this, false, t)
        # #Implementation
        # imp = getPersonality().getImplementation(t)
        # if imp is None:
        #     raise UnsupportedPolymorphismException(this, true, t)
        #EnhNode
        # result = imp.wrap(self.asNode(), eg)
        # self.addView(result)
        # return t.cast(result)
    

    '''
     * answer true iff this enhanced node can support the class <code>t</code>,
     * ie it is already a value <code>t</code> or it can be reimplemented
     * as a <code>t</code> via the graph's personality's implementation.
     * If this node has no graph, answer false.
    '''
    #@Override
    # param Class<X> t
    # result <X extends RDFNode> boolean
    def canSupport(self, t):
        pass
        # if (alreadyHasView(t)) return true
        # if (getGraph() == null) return false
        # Implementation imp = getPersonality().getImplementation(t)
        # return imp == null ? false : imp.canWrap(asNode(), getGraph())
    

    '''
     * Answer the personality object bound to this enhanced node, which we obtain from
     * the associated enhanced graph.
     *
     * @return The personality object
    '''
    #@Override
    # param 
    # result Personality<RDFNode>
    def getPersonality(self):
        return self.getGraph().getPersonality()
    


